# -*- coding: utf-8 -*-

'''
/**
 * @file        fsm_tool.py
 * @brief       XXXX
 * @note        XXXX
 * @author      靳普诏(puzhao.jin@hopechart.com)
 * @date        2025/05/18
 * @version     1.0

 * @par         修改日志
 * <table>
 * <tr><th>Date         <th>Version     <th>Author      <th> Description
 * <tr><td>2025/05/18   <td>1.0         <td>靳普诏       <td> 创建初始版本
 * @copyright   xxxx
 */
'''

import sys
import os
import argparse

from datetime import datetime
# 获取当前日期
CURR_DATE_STRING = datetime.now().strftime("%Y-%m-%d")
# 获取当前时间
CURR_TIME_STRING = datetime.now().strftime("%H:%M:%S")
## 获取当前脚本所在的目录
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
# 输出目录路径
# print("SCRIPT_DIR: "+ SCRIPT_DIR)

import json

def ReadJsonFile(file_name: str) -> dict:
    try:
        with open(file_name, 'r', encoding='utf-8') as f:
            data = json.load(f)
        return data
    except Exception as e:
        print("读取json文件失败: ", str(e))
        return None

def WriteJsonFile(file_name: str, data: dict, encoding='utf-8') -> bool:
    try:
        with open(file_name, 'w', encoding=encoding) as f:
            json.dump(data, f, indent=4)
        print(f"File '{file_name}' is successfully generated.\n")
    except Exception as e:
        print("写入json文件失败: ", str(e))
        return False
    return True

from EasyJinja2 import TEasyJinja2


def TargetToFilename(target: str) -> str:
    """
    将目标名称转换为文件名
    :param target: 目标名称
    :return: 文件名
    """
    # 将目标名称中的空格、连字符和点替换为下划线, 如果中间是大写写字母，则转换为小写字母并在前面加下划线
    # 例如：MyTargetName -> my_target_name
    filename = ""
    for i, char in enumerate(target):
        if char.isupper() and i > 0:
            filename += "_"
        filename += char.lower()
    filename = filename.replace(" ", "_").replace("-", "_").replace(".", "_")
    return filename



def CopyFile(source_filename: str, dest_filename: str, show_log: bool = True):
    """
    将源文件复制到目标文件。

    参数:
        source_filename (str): 源文件的路径。
        dest_filename (str): 目标文件的路径。

    异常:
        FileNotFoundError: 如果源文件不存在。
        ValueError: 如果目标文件位于源文件的目录内。
        Exception: 在文件操作过程中遇到其他错误。
    """

    # 验证源文件
    if not os.path.isfile(source_filename):
        raise FileNotFoundError(f"源文件 {source_filename} 不存在。")

    # 验证并准备目标文件路径
    if os.path.commonprefix([source_filename, dest_filename]) == source_filename:
        raise ValueError("目标文件路径位于源文件路径的目录内，不安全。")

    # 进行文件复制并处理异常
    try:
        with open(source_filename, 'rb') as r_f:
            with open(dest_filename, 'wb') as w_f:
                # 改进的复制大文件的方法
                buffer_size = 4096  # 4KB 缓冲区
                while True:
                    chunk = r_f.read(buffer_size)
                    if not chunk:
                        break
                    w_f.write(chunk)
        if show_log:
            print(f"文件 {source_filename} 已复制到 {dest_filename}。")
    except Exception as e:
        # 可以进一步细化以处理特定异常
        raise Exception(f"在复制文件时发生错误: {str(e)}")


if __name__ == "__main__":


    ## 获取脚本传参
    argv = sys.argv
    argc = len(argv)
    # 打印命令行参数
    #for i in range(1, argc):
        #print("参数", i, ":", argv[i])


    #设置命令行参数解析器
    parser = argparse.ArgumentParser(description='fsm_tool.py - Gen code file about fsm', usage="fsm_tool.py cfg.json -o <output_dir> [-n]")
    # 必填项 传入的cfg文件路径. 示例 fsm_tool.py xxx.json
    parser.add_argument('cfg_file', type=str, help='Input cfg file path')

    # 可选项 -r 指令执行指定的脚本列表. 示例 fsm_tool.py xxx.json -r a b c
    parser.add_argument('-o', '--out_path', action='store', type=str, help='Output directory path')

    # 存在时 -n 指令新建一个cfg文件到cfg_file路径下
    # -n 指令新建一个cfg文件到cfg_file路径下
    # 示例 fsm_tool.py xxx.json -n
    parser.add_argument('-n', '--new', action='store_true', help='Create a new cfg file')

    #解析命令行参数
    args = parser.parse_args()

    if args.new:
        print("创建一个新的cfg文件")
        cfg_file = args.cfg_file
        # 复制fsm_def.json文件到cfg_file路径下
        CopyFile(SCRIPT_DIR + "/fsm_def.json", cfg_file)
        print(f"新建cfg文件成功: {cfg_file}")
        exit(0)

    print("============= BIGEN: fsm_tool.py =============")

    JSON_FILE = args.cfg_file

    # 读取json文件
    json_data = ReadJsonFile(JSON_FILE)
    if json_data is None:
        print("读取json文件失败")
        exit(1)

    G_TARGET = json_data["Target"]
    print("G_TARGET: ", G_TARGET)
    FNAME_TAG = json_data["FNAME_TAG"]
    if FNAME_TAG == None  or FNAME_TAG == "":
        print("FNAME_TAG is empty")
        FNAME_TAG = TargetToFilename(G_TARGET)
    print("FNAME_TAG: ", FNAME_TAG)

    json_data["FNameTag"] = FNAME_TAG

    # 为每个状态创建一个int索引，并保存在json_data["State"]中，方便后续使用值
    # 这里假设json_data["State"]是一个列表
    # 如果没有eid，则使用索引作为状态ID
    for i, state in enumerate(json_data["StateDef"]):
        if "eid" not in state:
            state["eid"] = i
    # 将eid保存回json文件
    # WriteJsonFile(JSON_FILE, json_data)


#================================================================================

    TPL_DIR = SCRIPT_DIR + "/../ref/c/"
    # 创建输出目录
    OUT_DIR = args.out_path
    print("OUT_DIR: ", OUT_DIR)
    if not os.path.exists(OUT_DIR):
        os.makedirs(OUT_DIR)


    # 创建TEasyJinja2对象
    jinja2 = TEasyJinja2(TPL_DIR)


    T_TPL_NAME = "fsm.h"
    O_FILENAME = f"{OUT_DIR}/{FNAME_TAG}_{T_TPL_NAME}"
    jinja2.Render(json_data, T_TPL_NAME+'.j2', O_FILENAME)
    print(f"生成 {O_FILENAME} 文件成功")

    T_TPL_NAME = "fsm.c"
    O_FILENAME = f"{OUT_DIR}/{FNAME_TAG}_{T_TPL_NAME}"
    jinja2.Render(json_data, T_TPL_NAME+'.j2', O_FILENAME)
    print(f"生成 {O_FILENAME} 文件成功")

    T_TPL_NAME = "fsm_cjm.c"
    O_FILENAME = f"{OUT_DIR}/{FNAME_TAG}_{T_TPL_NAME}"
    jinja2.Render(json_data, T_TPL_NAME+'.j2', O_FILENAME)
    print(f"生成 {O_FILENAME} 文件成功")

    T_TPL_NAME = "fsm_cjm.h"
    O_FILENAME = f"{OUT_DIR}/{FNAME_TAG}_{T_TPL_NAME}"
    jinja2.Render(json_data, T_TPL_NAME+'.j2', O_FILENAME)
    print(f"生成 {O_FILENAME} 文件成功")

    T_TPL_NAME = "fsm_fcm.c"
    O_FILENAME = f"{OUT_DIR}/{FNAME_TAG}_{T_TPL_NAME}"
    jinja2.Render(json_data, T_TPL_NAME+'.j2', O_FILENAME)
    print(f"生成 {O_FILENAME} 文件成功")

    T_TPL_NAME = "fsm_fcm.h"
    O_FILENAME = f"{OUT_DIR}/{FNAME_TAG}_{T_TPL_NAME}"
    jinja2.Render(json_data, T_TPL_NAME+'.j2', O_FILENAME)
    print(f"生成 {O_FILENAME} 文件成功")
    

    ##--- 不用输入末尾下划线 -------------------------
    T_TPL_NAME = ".h"
    O_FILENAME = f"{OUT_DIR}/{FNAME_TAG}{T_TPL_NAME}"
    jinja2.Render(json_data, T_TPL_NAME+'.j2', O_FILENAME)
    print(f"生成 {O_FILENAME} 文件成功")

    T_TPL_NAME = ".c"
    O_FILENAME = f"{OUT_DIR}/{FNAME_TAG}{T_TPL_NAME}"
    jinja2.Render(json_data, T_TPL_NAME+'.j2', O_FILENAME)
    print(f"生成 {O_FILENAME} 文件成功")

    print("============= END: fsm_tool.py =============")



